//
// Created by work on 24-8-28.
//

#include "iot_model_device/device_model_mgr/CRedisDbMgr.h"
#include <sw/redis++/redis.h>
#include <dist/json/json.h>
#include <iot_model_device/device_model_mgr/CSsqlMgr.h>
#include <mqtt/log.hpp>

namespace iotplat {
    bool iotplat::CRedisDbMgr::loadUser(std::string &userid) {
        Json::Value userjson;
        if(!CSsqlMgr::getUser(userid, userjson)){
            OUTPUT_WARNING_INFO(std::string("db get user flied! user=" + userid));
            return false;
        }

        std::unordered_map<std::string, std::string> userRtInfo = {
                /*关系库部分*/
                {userFieldName(USER_ENUM::EUserId), userjson[userFieldName(USER_ENUM::EUserId)].asString()},
                {userFieldName(USER_ENUM::EPwd), userjson[userFieldName(USER_ENUM::EPwd)].asString()},
                {userFieldName(USER_ENUM::ENickname), userjson[userFieldName(USER_ENUM::ENickname)].asString()},
                {userFieldName(USER_ENUM::EUtype), std::to_string(userjson[userFieldName(USER_ENUM::EUtype)].asInt())},
                {userFieldName(USER_ENUM::EAdmin_usr), userjson[userFieldName(USER_ENUM::EAdmin_usr)].asString()},
                {userFieldName(USER_ENUM::EConfigs), userjson[userFieldName(USER_ENUM::EConfigs)].toStyledString().c_str()},
                {userFieldName(USER_ENUM::EMenu_permission), userjson[userFieldName(USER_ENUM::EMenu_permission)].toStyledString().c_str()},
                {userFieldName(USER_ENUM::EProperty_permission), userjson[userFieldName(USER_ENUM::EProperty_permission)].toStyledString().c_str()},
                {userFieldName(USER_ENUM::EGroupings), userjson[userFieldName(USER_ENUM::EGroupings)].asString()},
                {userFieldName(USER_ENUM::ECreate_time), userjson[userFieldName(USER_ENUM::ECreate_time)].asString()},
                {userFieldName(USER_ENUM::EUpdate_time), userjson[userFieldName(USER_ENUM::EUpdate_time)].asString()},
                {userFieldName(USER_ENUM::ELast_online_time), userjson[userFieldName(USER_ENUM::ELast_online_time)].asString()},
                {userFieldName(USER_ENUM::ELast_login_time), userjson[userFieldName(USER_ENUM::ELast_login_time)].asString()},
                {userFieldName(USER_ENUM::EMail_address), userjson[userFieldName(USER_ENUM::EMail_address)].asString()},
                {userFieldName(USER_ENUM::EMail_address),userjson[userFieldName(USER_ENUM::EPhone_number)].asString()},
                /*实时部分，登陆之后才会操作*/
                {userRtColToStringMap.find(CUserInfo::ECommunication_key)->second, "test"},
                {userRtColToStringMap.find(CUserInfo::EState)->second, boolToString.find(false)->second},
                {userRtColToStringMap.find(CUserInfo::EPulse)->second, "300"},
                {userRtColToStringMap.find(CUserInfo::ELogin_time)->second,CDateTime().ToString()}
        };

        std::string indexkey = std::string(user_key+"."+index_key);
        std::string datakey = std::string(user_key+"."+userid);

        if(!redisAddSetValue(indexkey, userid) || !redisAddHashMap(datakey, userRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load user fail!" + indexkey));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::unLoadUser(std::string &userid) {
        GET_REDIS_HANDLE;
        std::string indexkey = std::string(user_key+"."+index_key);
        std::string datakey = std::string(user_key+"."+userid);
        if( !redisRemoveSetValue(indexkey, userid) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload user fail!" + userid));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getRtUser(const std::string &userid, CUserInfo &user) {
        std::string datakey = std::string(user_key+"."+userid);
        std::unordered_map<std::string, std::string> hashUser;

        if(!getHashAllValue(datakey, hashUser)) {
            return false;
        }

        user.userid = hashUser[userFieldName(USER_ENUM::EUserId)];
        user.pwd = hashUser[userFieldName(USER_ENUM::EPwd)];
        user.nickname = hashUser[userFieldName(USER_ENUM::ENickname)];
        user.utype = static_cast<CUserInfo::EUserType>(std::stoi(hashUser[userFieldName(USER_ENUM::EUtype)]));
        user.admin = hashUser[userFieldName(USER_ENUM::EAdmin_usr)];
        user.configs = stringToJson(hashUser[userFieldName(USER_ENUM::EConfigs)]);
        user.menu_permission = stringToJson(hashUser[userFieldName(USER_ENUM::EMenu_permission)]);
        user.property_permission = stringToJson(hashUser[userFieldName(USER_ENUM::EProperty_permission)]);
        user.grouping = hashUser[userFieldName(USER_ENUM::EGroupings)];
        user.create_time = CDateTime::FromString(hashUser[userFieldName(USER_ENUM::ECreate_time)]);
        user.update_time = CDateTime::FromString(hashUser[userFieldName(USER_ENUM::EUpdate_time)]);
        user.last_online_time = CDateTime::FromString(hashUser[userFieldName(USER_ENUM::ELast_online_time)]);
        user.last_login_time = CDateTime::FromString(hashUser[userFieldName(USER_ENUM::ELast_login_time)]);
        user.email_address = hashUser[userFieldName(USER_ENUM::EMail_address)];
        user.phone_number = hashUser[userFieldName(USER_ENUM::EPhone_number)];
        return true;
    }

    bool CRedisDbMgr::checkUserExist(std::string &userid) {
        std::string indexkey = std::string(user_key+"."+index_key);
        GET_REDIS_HANDLE;
        return redis->sismember(indexkey, userid);
    }

    bool CRedisDbMgr::loadModel(const std::string& userid, const std::string& modelname) {
        CModelInfo model;
        if(!CSsqlMgr::getModel(userid, modelname, model)){
            OUTPUT_WARNING_INFO(std::string("db get model flied! user=" + userid));
            return false;
        }

        std::unordered_map<std::string, std::string> modelRtInfo = {
                {mdoelFieldName(MODEL_ENUM::EUser), model.user},
                {mdoelFieldName(MODEL_ENUM::EName), model.name},
                {mdoelFieldName(MODEL_ENUM::EDescr), model.descr},
                {mdoelFieldName(MODEL_ENUM::ESn), std::to_string(model.sn)},
                {mdoelFieldName(MODEL_ENUM::EGroupIngs), model.grouping},
                {mdoelFieldName(MODEL_ENUM::ELocation), model.location},
                {mdoelFieldName(MODEL_ENUM::ECreate_time), model.create_time.ToString()},
                {mdoelFieldName(MODEL_ENUM::EUpdate_time), model.update_time.ToString()},
                {mdoelFieldName(MODEL_ENUM::EProducer), model.producer},
                {mdoelFieldName(MODEL_ENUM::EValid), BOOL_TO_STRING(model.valid)},
                {mdoelFieldName(MODEL_ENUM::EConfigs), model.configs.toStyledString().c_str()}
        };

        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+index_key);
        std::string datakey = std::string(user_key+"."+userid+"."+ model_key+ "." + modelname);

        if(!redisAddSetValue(indexkey, modelname) || !redisAddHashMap(datakey, modelRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load model fail!" + indexkey));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getRtModel(std::string &userid, std::string &modelname, CModelInfo &model) {
        std::string datakey = std::string(user_key+"."+userid+"."+ model_key+ "." + modelname);
        std::unordered_map<std::string, std::string> hashModel;

        if(!getHashAllValue(datakey, hashModel)) {
            return false;
        }

        model.user = hashModel[mdoelFieldName(MODEL_ENUM::EUser)];
        model.name = hashModel[mdoelFieldName(MODEL_ENUM::EName)];
        model.descr = hashModel[mdoelFieldName(MODEL_ENUM::EDescr)];
        model.sn = std::stoi(hashModel[mdoelFieldName(MODEL_ENUM::ESn)]);
        model.grouping = hashModel[mdoelFieldName(MODEL_ENUM::EGroupIngs)];
        model.location = hashModel[mdoelFieldName(MODEL_ENUM::ELocation)];
        model.create_time = CDateTime::FromString(hashModel[mdoelFieldName(MODEL_ENUM::ECreate_time)]);
        model.update_time = CDateTime::FromString(hashModel[mdoelFieldName(MODEL_ENUM::EUpdate_time)]);
        model.producer = hashModel[mdoelFieldName(MODEL_ENUM::EProducer)];
        model.valid = STRING_TO_BOOL(hashModel[mdoelFieldName(MODEL_ENUM::EValid)]);
        Json::Value root;
        std::string jsonString = hashModel[mdoelFieldName(MODEL_ENUM::EConfigs)];
        std::string errors;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        model.configs = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &root, &errors) ? root : Json::Value(Json::nullValue);

        return true;
    }

    bool CRedisDbMgr::unLoadModel(std::string &userid, std::string& modelname) {
        GET_REDIS_HANDLE;

        std::unordered_set<std::string> yxidxs;
        if(!getModelYxIndexs(userid, modelname, yxidxs)) {
            return false;
        }
        if(!yxidxs.empty()) {
            for(std::string name : yxidxs) {
                if(!unLoadModelYx(userid, modelname, name)) {
                    return false;
                }
            }
            OUTPUT_DEBUG_INFO(std::string(userid+"."+modelname+ " unload all yx successful!"));
        }

        std::unordered_set<std::string> ycidxs;
        if(!getModelYcIndexs(userid, modelname, ycidxs)) {
            return false;
        }
        if(!ycidxs.empty()) {
            for(std::string name : ycidxs) {
                if(!unLoadModelYc(userid, modelname, name)) {
                    return false;
                }
            }
            OUTPUT_DEBUG_INFO(std::string(userid+"."+modelname+ " unload all yc successful!"));
        }

        std::unordered_set<std::string> ykidxs;
        if(!getModelYkIndexs(userid, modelname, ykidxs)) {
            return false;
        }
        if(!ykidxs.empty()) {
            for(std::string name : ykidxs) {
                if(!unLoadModelYk(userid, modelname, name)) {
                    return false;
                }
            }
            OUTPUT_DEBUG_INFO(std::string(userid+"."+modelname+ " unload all yk successful!"));
        }

        std::unordered_set<std::string> parameteridxs;
        if(!getModelParameterIndexs(userid, modelname, parameteridxs)) {
            return false;
        }
        if(!parameteridxs.empty()) {
            for(std::string name : parameteridxs) {
                if(!unLoadModelParameter(userid, modelname, name)) {
                    return false;
                }
            }
            OUTPUT_DEBUG_INFO(std::string(userid+"."+modelname+ " unload all parameter successful!"));
        }

        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+index_key);
        std::string datakey = std::string(user_key+"."+userid+"."+ model_key+ "." + modelname);
        if( !redisRemoveSetValue(indexkey, modelname) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload model fail!" + userid));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getModelIndexs(const std::string &userid, std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::loadModelYx(std::string &userid, std::string &modelname, std::string &yx) {
        CRtModelYxInfo jsonyx;
        if(!CSsqlMgr::getYx(userid, modelname, yx, jsonyx)){
            OUTPUT_WARNING_INFO(std::string("db get yx flied! yx=" + yx));
            return false;
        }

        Json::Value obj;
        obj["values"] = jsonyx.valuesToJson();

        std::unordered_map<std::string, std::string> yxRtInfo = {
                {baseSigFieldName(BASE_SIG_ENUM::EModel_name), jsonyx.model_name},
                {baseSigFieldName(BASE_SIG_ENUM::EUser), jsonyx.user},
                {baseSigFieldName(BASE_SIG_ENUM::EName), jsonyx.name},
                {baseSigFieldName(BASE_SIG_ENUM::EDescr), jsonyx.descr},
                {baseSigFieldName(BASE_SIG_ENUM::ESn), std::to_string(jsonyx.sn)},
                {baseSigFieldName(BASE_SIG_ENUM::EGrouping), jsonyx.grouping},
                {baseSigFieldName(BASE_SIG_ENUM::EConfigs), jsonyx.configs.toStyledString().c_str()},
                {yxFieldName(YX_ENUM::EValues), obj.toStyledString().c_str()}
        };

        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yx_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yx_key + "." + yx);

        if(!redisAddSetValue(indexkey, yx) || !redisAddHashMap(datakey, yxRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load yx fail!" + indexkey));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getRtModelYx(std::string &userid, std::string &modelname, std::string &yxName, CRtModelYxInfo &yx) {
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yx_key + "." + yxName);
        std::unordered_map<std::string, std::string> hashYx;
        if(!getHashAllValue(datakey, hashYx)) {
            return false;
        }

        yx.model_name = hashYx[baseSigFieldName(BASE_SIG_ENUM::EModel_name)];
        yx.user = hashYx[baseSigFieldName(BASE_SIG_ENUM::EUser)];
        yx.name = hashYx[baseSigFieldName(BASE_SIG_ENUM::EName)];
        yx.descr = hashYx[baseSigFieldName(BASE_SIG_ENUM::EDescr)];
        yx.sn = std::stoi(hashYx[baseSigFieldName(BASE_SIG_ENUM::ESn)]);
        yx.grouping = hashYx[baseSigFieldName(BASE_SIG_ENUM::EGrouping)];
        yx.configs = stringToJson(hashYx[baseSigFieldName(BASE_SIG_ENUM::EConfigs)]);

        Json::Value jsonvalues = stringToJson(hashYx[yxFieldName(YX_ENUM::EValues)]);
        yx.valuesFromJson(jsonvalues["values"]);
        return true;
    }

    bool CRedisDbMgr::unLoadModelYx(std::string &userid, std::string &modelname, std::string &yx) {
        GET_REDIS_HANDLE;
        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yx_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yx_key + "." + yx);
        if( !redisRemoveSetValue(indexkey, yx) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload model fail!" + userid));
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::getModelYxIndexs(const std::string &userid, const std::string &modelname,
                                       std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+modelname+"."+ yx_key +"." + index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::loadModelYc(const std::string &userid, const std::string &modelname, const std::string &yc) {
        CRtModelYcInfo jsonyc;
        if(!CSsqlMgr::getYc(userid, modelname, yc, jsonyc)){
            OUTPUT_WARNING_INFO(std::string("db get yx flied! yc=" + yc));
            return false;
        }

        std::unordered_map<std::string, std::string> ycRtInfo = {
                {baseSigFieldName(BASE_SIG_ENUM::EModel_name), jsonyc.model_name},
                {baseSigFieldName(BASE_SIG_ENUM::EUser), jsonyc.user},
                {baseSigFieldName(BASE_SIG_ENUM::EName), jsonyc.name},
                {baseSigFieldName(BASE_SIG_ENUM::EDescr), jsonyc.descr},
                {baseSigFieldName(BASE_SIG_ENUM::ESn), std::to_string(jsonyc.sn)},
                {baseSigFieldName(BASE_SIG_ENUM::EGrouping), jsonyc.grouping},
                {baseSigFieldName(BASE_SIG_ENUM::EConfigs), jsonyc.configs.toStyledString().c_str()},
                {ycFieldName(YC_ENUM::EBase), std::to_string(jsonyc.base)},
                {ycFieldName(YC_ENUM::ECoef), std::to_string(jsonyc.coef)},
                {ycFieldName(YC_ENUM::EEn_alarm), BOOL_TO_STRING(jsonyc.en_alarm)},
                {ycFieldName(YC_ENUM::EAlarm_up_limit), std::to_string(jsonyc.alarm_up_limit)},
                {ycFieldName(YC_ENUM::EAlarm_down_limit), std::to_string(jsonyc.alarm_down_limit)},
                {ycFieldName(YC_ENUM::EAlarm_up_limit_desc), jsonyc.alarm_up_limit_desc},
                {ycFieldName(YC_ENUM::EAlarm_down_limit_desc), jsonyc.alarm_down_limit_desc},
                {ycFieldName(YC_ENUM::EAlarm_time_count), std::to_string(jsonyc.alarm_time_count)}
        };

        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yc_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yc_key + "." + yc);

        if(!redisAddSetValue(indexkey, yc) || !redisAddHashMap(datakey, ycRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load yc fail!" + indexkey));
            return false;
        }

        return true;

    }

    bool CRedisDbMgr::getRtModelYc(std::string &userid, std::string &modelname, std::string &ycName, CRtModelYcInfo &yc) {
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yc_key + "." + ycName);
        std::unordered_map<std::string, std::string> hashYc;
        if(!getHashAllValue(datakey, hashYc)) {
            return false;
        }

        yc.model_name = hashYc[baseSigFieldName(BASE_SIG_ENUM::EModel_name)];
        yc.user = hashYc[baseSigFieldName(BASE_SIG_ENUM::EUser)];
        yc.name = hashYc[baseSigFieldName(BASE_SIG_ENUM::EName)];
        yc.descr = hashYc[baseSigFieldName(BASE_SIG_ENUM::EDescr)];
        yc.sn = std::stoi(hashYc[baseSigFieldName(BASE_SIG_ENUM::ESn)]);
        yc.grouping = hashYc[baseSigFieldName(BASE_SIG_ENUM::EGrouping)];
        Json::Value root;
        std::string jsonString = hashYc[baseSigFieldName(BASE_SIG_ENUM::EConfigs)];
        std::string errors;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        yc.configs = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &root, &errors) ? root : Json::Value(Json::nullValue);
        yc.base = std::stof(hashYc[ycFieldName(YC_ENUM::EBase)]);
        yc.coef = std::stof(hashYc[ycFieldName(YC_ENUM::ECoef)]);
        yc.en_alarm = STRING_TO_BOOL(hashYc[ycFieldName(YC_ENUM::EEn_alarm)]);
        yc.alarm_up_limit = std::stof(hashYc[ycFieldName(YC_ENUM::EAlarm_up_limit)]);
        yc.alarm_down_limit = std::stof(hashYc[ycFieldName(YC_ENUM::EAlarm_down_limit)]);
        yc.alarm_up_limit_desc = hashYc[ycFieldName(YC_ENUM::EAlarm_up_limit_desc)];
        yc.alarm_down_limit_desc = hashYc[ycFieldName(YC_ENUM::EAlarm_down_limit_desc)];
        yc.alarm_time_count = std::stoi(hashYc[ycFieldName(YC_ENUM::EAlarm_time_count)]);
        return true;
    }

    bool CRedisDbMgr::unLoadModelYc(std::string &userid, std::string &modelname, std::string &yc) {
        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yc_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yc_key + "." + yc);
        if( !redisRemoveSetValue(indexkey, yc) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload model fail!" + userid));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getModelYcIndexs(const std::string &userid, const std::string &modelname,
                                       std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+modelname+"."+ yc_key +"." + index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::loadModelYk(const std::string& userid, const std::string& modelname, const std::string& yk) {
        CRtModelYkInfo jsonyk;
        if(!CSsqlMgr::getYk(userid, modelname, yk, jsonyk)){
            OUTPUT_WARNING_INFO(std::string("db get yk flied! yk=" + yk));
            return false;
        }

        Json::Value obj;
        obj[ykFieldName(YK_ENUM::EValues)] = jsonyk.valuesToJson();
        std::unordered_map<std::string, std::string> ykRtInfo = {
                {baseSigFieldName(BASE_SIG_ENUM::EModel_name), jsonyk.model_name},
                {baseSigFieldName(BASE_SIG_ENUM::EUser), jsonyk.user},
                {baseSigFieldName(BASE_SIG_ENUM::EName), jsonyk.name},
                {baseSigFieldName(BASE_SIG_ENUM::EDescr), jsonyk.descr},
                {baseSigFieldName(BASE_SIG_ENUM::ESn), std::to_string(jsonyk.sn)},
                {baseSigFieldName(BASE_SIG_ENUM::EGrouping), jsonyk.grouping},
                {baseSigFieldName(BASE_SIG_ENUM::EConfigs), jsonyk.configs.toStyledString().c_str()},
                {ykFieldName(YK_ENUM::EEn_write), BOOL_TO_STRING(jsonyk.en_write)},
                {ykFieldName(YK_ENUM::EValues), obj.toStyledString().c_str()},
        };

        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yk_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yk_key + "." + yk);

        if(!redisAddSetValue(indexkey, yk) || !redisAddHashMap(datakey, ykRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load yk fail!" + indexkey));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getRtModelYk(std::string &userid, std::string &modelname, std::string &ykName, CRtModelYkInfo &yk) {
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yk_key + "." + ykName);
        std::unordered_map<std::string, std::string> hashYk;
        if(!getHashAllValue(datakey, hashYk)) {
            return false;
        }

        yk.model_name = hashYk[baseSigFieldName(BASE_SIG_ENUM::EModel_name)];
        yk.user = hashYk[baseSigFieldName(BASE_SIG_ENUM::EUser)];
        yk.name = hashYk[baseSigFieldName(BASE_SIG_ENUM::EName)];
        yk.descr = hashYk[baseSigFieldName(BASE_SIG_ENUM::EDescr)];
        yk.sn = std::stoi(hashYk[baseSigFieldName(BASE_SIG_ENUM::ESn)]);
        yk.grouping = hashYk[baseSigFieldName(BASE_SIG_ENUM::EGrouping)];
        Json::Value root;
        std::string jsonString = hashYk[baseSigFieldName(BASE_SIG_ENUM::EConfigs)];
        std::string errors;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        yk.configs = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &root, &errors) ? root : Json::Value(Json::nullValue);
        yk.en_write = STRING_TO_BOOL(hashYk[ykFieldName(YK_ENUM::EEn_write)]);
        Json::Value jsonvalues = stringToJson(hashYk[ykFieldName(YK_ENUM::EValues)]);
        yk.valuesFromJson(jsonvalues[ykFieldName(YK_ENUM::EValues)]);
        return true;
    }

    bool CRedisDbMgr::unLoadModelYk(std::string &userid, std::string &modelname, std::string &yk) {
        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+yk_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+yk_key + "." + yk);
        if( !redisRemoveSetValue(indexkey, yk) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload model fail!" + userid));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getModelYkIndexs(const std::string &userid, const std::string &modelname,
                                       std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+modelname+"."+ yk_key +"." + index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::loadModelParameter(const std::string &userid, const std::string &modelname, const std::string &parameter) {
        CRtModelParameterInfo jsonparameter;
        if(!CSsqlMgr::getParameter(userid, modelname, parameter, jsonparameter)){
            OUTPUT_WARNING_INFO(std::string("db get parameter flied! parameter=" + parameter));
            return false;
        }

        std::unordered_map<std::string, std::string> parameterRtInfo = {
                {baseSigFieldName(BASE_SIG_ENUM::EModel_name), jsonparameter.model_name},
                {baseSigFieldName(BASE_SIG_ENUM::EUser), jsonparameter.user},
                {baseSigFieldName(BASE_SIG_ENUM::EName), jsonparameter.name},
                {baseSigFieldName(BASE_SIG_ENUM::EDescr), jsonparameter.descr},
                {baseSigFieldName(BASE_SIG_ENUM::ESn), std::to_string(jsonparameter.sn)},
                {baseSigFieldName(BASE_SIG_ENUM::EGrouping), jsonparameter.grouping},
                {baseSigFieldName(BASE_SIG_ENUM::EConfigs), jsonparameter.configs.toStyledString().c_str()},
                {parameterFieldName(PARAMETER_ENUM::EPtype), std::to_string(jsonparameter.ptype)},
                {parameterFieldName(PARAMETER_ENUM::EEn_write), BOOL_TO_STRING(jsonparameter.en_write)},
                {parameterFieldName(PARAMETER_ENUM::EEn_read), BOOL_TO_STRING(jsonparameter.en_read)}
        };

        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+parameter_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+parameter_key + "." + parameter);

        if(!redisAddSetValue(indexkey, parameter) || !redisAddHashMap(datakey, parameterRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load parameter fail!" + indexkey));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getRtModelParameter(std::string &userid, std::string &modelname, std::string &parameterName,
                                          CRtModelParameterInfo &parameter) {
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+parameter_key + "." + parameterName);
        std::unordered_map<std::string, std::string> hashParameter;
        if(!getHashAllValue(datakey, hashParameter)) {
            return false;
        }

        parameter.model_name = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EModel_name)];
        parameter.user = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EUser)];
        parameter.name = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EName)];
        parameter.descr = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EDescr)];
        parameter.sn = std::stoi(hashParameter[baseSigFieldName(BASE_SIG_ENUM::ESn)]);
        parameter.grouping = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EGrouping)];
        Json::Value root;
        std::string jsonString = hashParameter[baseSigFieldName(BASE_SIG_ENUM::EConfigs)];
        std::string errors;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        parameter.configs = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &root, &errors) ? root : Json::Value(Json::nullValue);
        parameter.ptype = static_cast<CRtModelParameterInfo::EParameterType> (std::stoi(hashParameter[parameterFieldName(PARAMETER_ENUM::EPtype)]));
        parameter.en_write = STRING_TO_BOOL(hashParameter[parameterFieldName(PARAMETER_ENUM::EEn_write)]);
        parameter.en_read = STRING_TO_BOOL(hashParameter[parameterFieldName(PARAMETER_ENUM::EEn_read)]);
        return true;
    }

    bool CRedisDbMgr::unLoadModelParameter(std::string &userid, std::string &modelname, std::string &parameter) {
        std::string indexkey = std::string(user_key+"."+userid+"."+model_key+"."+modelname+"."+parameter_key+"."+index_key);
        std::string datakey = std::string(user_key + "."+ userid + "." + model_key+"."+modelname+"."+parameter_key + "." + parameter);
        if( !redisRemoveSetValue(indexkey, parameter) || !redisRemoveHashMap(datakey) ) {
            OUTPUT_WARNING_INFO(std::string("unload model fail!" + userid));
            return false;
        }

        return true;
    }

    bool CRedisDbMgr::getModelParameterIndexs(const std::string &userid, const std::string &modelname,
                                              std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key+"."+userid+"."+ model_key+"."+modelname+"."+ parameter_key +"." + index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::loadDevice(const std::string &userid, const std::string &modelname, const std::string name) {
        CRtDeviceInfo info;
        if(!CSsqlMgr::getDevice(userid, modelname, name, info)) {
            OUTPUT_WARNING_INFO(std::string("load device fail!" + userid+"."+modelname+"."+name));
            return false;
        }

        std::unordered_map<std::string, std::string> deviceRtInfo = {
            {deviceFieldName(DEVICE_ENUM::EUser), info.user},
            {deviceFieldName(DEVICE_ENUM::EName), info.name},
            {deviceFieldName(DEVICE_ENUM::EModelName), info.model_name},
            {deviceFieldName(DEVICE_ENUM::EDescr), info.descr},
            {deviceFieldName(DEVICE_ENUM::ESn), std::to_string(info.sn)},
            {deviceFieldName(DEVICE_ENUM::EGroupIngs), info.grouping},
            {deviceFieldName(DEVICE_ENUM::EConfigs), info.configs.toStyledString().c_str()},
            {deviceFieldName(DEVICE_ENUM::ELocation), info.location},
            {deviceFieldName(DEVICE_ENUM::ECreate_time), info.create_time.ToString().c_str()},
            {deviceFieldName(DEVICE_ENUM::EProtocol), info.protocol},
            {deviceFieldName(DEVICE_ENUM::EFirmwareVersion), info.firmware_version},
            {deviceFieldName(DEVICE_ENUM::ELastOnlineTime), info.last_online_time.ToString().c_str()},
            {deviceFieldName(DEVICE_ENUM::EAccruedOnlineTime), std::to_string(info.accrued_online_time)},
            {deviceFieldName(DEVICE_ENUM::ESpecifications), info.specifications},
            {deviceFieldName(DEVICE_ENUM::EValid), BOOL_TO_STRING(info.valid)},

            {deviceFieldName(DEVICE_ENUM::EPulse), std::to_string(info.pulse)},
            {deviceFieldName(DEVICE_ENUM::ELoginTime), info.login_time.ToString().c_str()},
            {deviceFieldName(DEVICE_ENUM::EOnlineState), BOOL_TO_STRING(info.online_state)}
        };

        std::string indexkey = std::string(user_key +" ." + userid + "." + device_key + "." + index_key);
        std::string datakey  = std::string(user_key + "." + userid + "." + device_key + "." + name);

        if(!redisAddSetValue(indexkey, name) || !redisAddHashMap(datakey, deviceRtInfo)) {
            OUTPUT_WARNING_INFO(std::string("load device fail!" + indexkey));
            return false;
        }

        /*加载设备遥信*/
        std::unordered_set<std::string> yxNames;
        if(!getModelYxIndexs(userid, modelname, yxNames)) {
            OUTPUT_WARNING_INFO(std::string("load device yx error!" + datakey));
            return false;
        }
        std::unordered_map<std::string, std::string> deviceYxRtInfo = SRtDeviceYxInfo().toUnorderedMap();
        for(const auto& yxname : yxNames) {
            std::string deviceYxDataKey = std::string(user_key + "." + userid + "." + device_key + "." + name + "." + yx_key + "." + yxname);
            if(!redisAddHashMap(deviceYxDataKey, deviceYxRtInfo)) {
                OUTPUT_WARNING_INFO(std::string("load device yx error!" + deviceYxDataKey));
                return false;
            }
        }

        /*加载设备遥测*/
        std::unordered_set<std::string> ycNames;
        if(!getModelYcIndexs(userid, modelname, ycNames)) {
            OUTPUT_WARNING_INFO(std::string("load device yc error!" + datakey));
            return false;
        }
        std::unordered_map<std::string, std::string> deviceYcRtInfo = SRtDeviceYcInfo().toUnorderedMap();
        for(const auto& ycname : ycNames) {
            std::string deviceYcDataKey = std::string(user_key + "." + userid + "." + device_key + "." + name + "." + yc_key + "." + ycname);
            if(!redisAddHashMap(deviceYcDataKey, deviceYcRtInfo)) {
                OUTPUT_WARNING_INFO(std::string("load device yc error!" + deviceYcDataKey));
                return false;
            }
        }

        /*加载设备遥控*/
        std::unordered_set<std::string> ykNames;
        if(!getModelYkIndexs(userid, modelname, ykNames)) {
            OUTPUT_WARNING_INFO(std::string("load device yk error!" + datakey));
            return false;
        }
        std::unordered_map<std::string, std::string> deviceYkRtInfo = SRtDeviceYkInfo().toUnorderedMap();

        for(const auto& ykname : ykNames) {
            std::string deviceYkDataKey = std::string(user_key + "." + userid + "." + device_key + "." + name + "." + yk_key + "." + ykname);
            if(!redisAddHashMap(deviceYkDataKey, deviceYkRtInfo)) {
                OUTPUT_WARNING_INFO(std::string("load device yc error!" + deviceYkDataKey));
                return false;
            }
        }

        /*加载设备参数*/
        std::unordered_set<std::string> parameterNames;
        if(!getModelParameterIndexs(userid, modelname, parameterNames)) {
            OUTPUT_WARNING_INFO(std::string("load device parameter error!" + datakey));
            return false;
        }
        std::unordered_map<std::string, std::string> deviceParameterRtInfo = SRtDeviceParameterInfo().toUnorderedMap();
        for(const auto& parametername : parameterNames) {
            std::string deviceParameterDataKey = std::string(user_key + "." + userid + "." + device_key + "." + name + "." + parameter_key + "." + parametername);
            if(!redisAddHashMap(deviceParameterDataKey, deviceParameterRtInfo)) {
                OUTPUT_WARNING_INFO(std::string("load device parameter error!" + deviceParameterDataKey));
                return false;
            }
        }

        return true;
    }

    bool CRedisDbMgr::getDeviceIndexs(const std::string &userid, const std::string &modelname,
        std::unordered_set<std::string> &idxs) {
        std::string indexkey = std::string(user_key +" ." + userid + "." + device_key + "." + index_key);
        return getSetAllValue(indexkey, idxs);
    }

    bool CRedisDbMgr::getRtDevice(const std::string &userid, const std::string &modelname, const std::string name,
                                  CRtDeviceInfo &device) {
        std::string datakey = std::string(user_key + "." + userid + "." + device_key + "." + name );
        std::unordered_map<std::string, std::string> hashDevice;
        if(!getHashAllValue(datakey, hashDevice)) {
            return false;
        }

        device.user = hashDevice[deviceFieldName(DEVICE_ENUM::EUser)];
        device.model_name = hashDevice[deviceFieldName(DEVICE_ENUM::EModelName)];
        device.name = hashDevice[deviceFieldName(DEVICE_ENUM::EName)];
        device.descr = hashDevice[deviceFieldName(DEVICE_ENUM::EDescr)];
        device.sn = std::stoi(hashDevice[deviceFieldName(DEVICE_ENUM::ESn)]);
        device.grouping = hashDevice[deviceFieldName(DEVICE_ENUM::EGroupIngs)];
        Json::Value root;
        std::string jsonString = hashDevice[deviceFieldName(DEVICE_ENUM::EConfigs)];
        std::string errors;
        Json::CharReaderBuilder builder;
        const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
        device.configs = reader->parse(jsonString.c_str(), jsonString.c_str() + jsonString.length(), &root, &errors) ? root : Json::Value(Json::nullValue);
        device.location = hashDevice[deviceFieldName(DEVICE_ENUM::ELocation)];
        device.create_time = CDateTime::FromString(hashDevice[deviceFieldName(DEVICE_ENUM::ECreate_time)]);
        device.protocol = hashDevice[deviceFieldName(DEVICE_ENUM::EProtocol)];
        device.firmware_version = hashDevice[deviceFieldName(DEVICE_ENUM::EFirmwareVersion)];
        device.last_online_time = CDateTime::FromString(hashDevice[deviceFieldName(DEVICE_ENUM::ELastOnlineTime)]);
        device.accrued_online_time = std::stoi(hashDevice[deviceFieldName(DEVICE_ENUM::EAccruedOnlineTime)]);
        device.specifications = hashDevice[deviceFieldName(DEVICE_ENUM::ESpecifications)];
        device.valid = STRING_TO_BOOL(hashDevice[deviceFieldName(DEVICE_ENUM::EValid)]);
        device.pulse = std::stoi(hashDevice[deviceFieldName(DEVICE_ENUM::EPulse)]);
        device.login_time = CDateTime::FromString(hashDevice[deviceFieldName(DEVICE_ENUM::ELoginTime)]);
        device.online_state = STRING_TO_BOOL(hashDevice[deviceFieldName(DEVICE_ENUM::EOnlineState)]);
        return true;
    }

    bool CRedisDbMgr::getRtDevices(const std::string &userid, const std::string &modelname,
        std::vector<CRtDeviceInfo> &devices) {
        return CSsqlMgr::getDevices(userid, modelname, devices);
    }

    bool CRedisDbMgr::reset() {
        GET_REDIS_HANDLE;
        redis->command("FLUSHALL");

        std::unordered_map<std::string, std::string> sysInfoMap = {
                {"start_time", CDateTime::Now().ToString()},
                {"model_loaded", "true"}
        };

        std::string key = "iot_plat_sys_info";

        return redisAddHashMap(key, sysInfoMap);
    }

    bool CRedisDbMgr::redisSetBoolFlag(const std::string &key, const std::string field, bool flag) {
        GET_REDIS_HANDLE;
        try {
            redis->hset(key, field, BOOL_TO_STRING(flag));
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::existsKey(std::string key) {
        GET_REDIS_HANDLE;
        return redis->exists(key);
    }

    bool CRedisDbMgr::getHashValueAsBool(const std::string &key, const std::string &field, bool &flag) {
        GET_REDIS_HANDLE;
        try {
            std::vector<sw::redis::OptionalString> vals;
            redis->hmget(key, {field}, std::back_inserter(vals));
            flag = STRING_TO_BOOL(vals.at(0)->c_str());
        } catch (const sw::redis::Error &e) {
            flag = false;
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::redisAddSetValue(const std::string& key, const std::string& value) {
        GET_REDIS_HANDLE;
        try {
            redis->sadd(key, value);
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::redisRemoveSetValue(const std::string& key, const std::string& value) {
        GET_REDIS_HANDLE;
        try {
            redis->srem(key, value);
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::redisRemoveSet(const std::string& key, const std::string& value) {
        return true;
    }

    bool CRedisDbMgr::redisAddHashMap(const std::string& key, std::unordered_map<std::string, std::string> &map) {
        GET_REDIS_HANDLE;
        try {
            redis->hmset(key, map.begin(), map.end());
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::redisRemoveHashMap(const std::string& key) {
        GET_REDIS_HANDLE;
        try {
            redis->del(key);
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::getHashAllValue(const std::string &key, std::unordered_map<std::string, std::string>& hashMap) {
        GET_REDIS_HANDLE;
        try {
            redis->hgetall(key, std::inserter(hashMap, hashMap.begin()));
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }

    bool CRedisDbMgr::getSetAllValue(const std::string &key, std::unordered_set<std::string> &set) {
        GET_REDIS_HANDLE;
        try {
            redis->smembers(key, std::inserter(set, set.begin()));
        } catch (const sw::redis::Error &e) {
            return false;
        }
        return true;
    }
}
